const { Strategy: JwtStrategy, ExtractJwt } = require('passport-jwt');
const passport = require('passport');
const httpStatus = require('http-status');
const config = require('./config');
const { User } = require('../models');
const Admin = require('../models/admin.model');
const ApiError = require('../utils/ApiError');
const redis = require('./redis');
const logger = require('./logger');

const jwtOptions = {
  secretOrKey: config.jwt.secret,
  jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
};

const jwtVerify = async (payload, done) => {
  try {
    // 打印载荷便于调试
    console.log('JWT载荷：', { ...payload, sub: payload.sub.substring(0, 8) + '...' });
    logger.info(`JWT验证: 用户ID=${payload.sub.substring(0, 8) + '...'}, 类型=${payload.userType}`);
    
    // 用户类型(admin或user)
    const userTypeFromPayload = payload.userType || 'user';
    
    // 检查Redis是否有此token，先构建Redis中存储的key
    const redisKey = `auth:${userTypeFromPayload}:${payload.sub}`;
    let cachedToken; // 将声明移到外部

    try {
      // 从Redis获取缓存的token
      cachedToken = await redis.get(redisKey);
      // 添加日志记录获取到的cachedToken状态
      logger.info(`Redis中的token检查: key=${redisKey}, Redis返回值: ${cachedToken === null ? 'null' : (cachedToken === undefined ? 'undefined' : '存在值')}, 值是否有效: ${!!cachedToken}`);
    } catch (redisError) {
      // 增强错误日志记录
      logger.error(`Redis获取令牌时出错: key=${redisKey}, error: ${redisError.message}`, { stack: redisError.stack });
      // 在这种情况下，cachedToken 将是 undefined
    }
    
    // 如果Redis中没有缓存token，可能是token已过期或被注销，或者获取时发生错误
    if (!cachedToken) {
      // 修改日志，更清晰地指出原因
      logger.warn(`无法从Redis获取有效的token缓存 (可能是未找到、获取错误或值无效): ${redisKey}`);
      return done(new ApiError(httpStatus.UNAUTHORIZED, 'Token会话无效或已过期，请重新登录'), false);
    }
    
    // 根据userType区分不同用户类型
    if (userTypeFromPayload === 'admin') {
      // 验证管理员令牌
      const admin = await Admin.findById(payload.sub);
      if (!admin) {
        logger.warn(`管理员不存在或已被删除，用户ID: ${payload.sub}`);
        return done(new ApiError(httpStatus.UNAUTHORIZED, '管理员不存在或已被删除'), false);
      }
      
      // 为管理员添加特殊标识
      admin.isAdmin = true;
      admin.userType = 'admin';
      
      // 将token中的权限信息附加到用户对象
      if (payload.permissions) {
        admin.permissions = payload.permissions;
      }
      
      logger.info(`验证管理员通过，ID: ${admin.id}`);
      return done(null, admin);
    } else {
      // 验证普通用户令牌
      const user = await User.findById(payload.sub);
      if (!user) {
        logger.warn(`用户不存在或已被删除，用户ID: ${payload.sub}`);
        return done(new ApiError(httpStatus.UNAUTHORIZED, '用户不存在或已被删除'), false);
      }
      user.userType = 'user';
      
      logger.info(`验证用户通过，ID: ${user.id}`);
      return done(null, user);
    }
  } catch (error) {
    logger.error(`JWT验证错误: ${error.message}`);
    done(error, false);
  }
};

const jwtStrategy = new JwtStrategy(jwtOptions, jwtVerify);

passport.use('jwt', jwtStrategy);

module.exports = {
  jwtStrategy,
}; 